#!/usr/bin/php
<?
if ($argc < 2 
        || in_array('-v', $argv)
        || in_array('-h', $argv)
        || in_array('--help', $argv)
)
{
    usage();
} else
{
    $exit = 0;
    $dir = array_pop($argv);
    if (!is_dir($dir))
    {
        echo "\033[22;31m";
        echo "Error: Invalid directory '$dir'\r\n";
        echo "\033[22;30m";
        usage();
    }
    ob_start('_ob_handler');
    set_error_handler('_ob_handler');
    require __find_autoload($dir);
    $tests = __find_tests($dir);
    for($i=0;$i<count($tests);$i++)
    {
        $test = $tests[$i];
        require_once($test);
        preg_match('/class\\s+(\\w+)/i', file_get_contents($test), $m);
        $test_class = $m[1];
        $test = new $test_class();
        $methods = get_class_methods($test);
        for($x = 0; $x < count($methods); $x++)
        {
            try
            {
                $method = $methods[$x];
                if(strpos($method, 'test_')===0)
                {
                    echo "\t".sprintf('%-50s', $test_class.'->'.$method);
                    if (!in_array('-q', $argv)) ob_flush();
                    echo "\033[22;31m";
                    $test->$method();
                    echo "\033[22;32m[PASSED]\033[22;30m";
                    echo "\r\n";
                    if (!in_array('-q', $argv)) ob_flush();
                }
            } catch (Exception $e)
            {
                if (in_array('-f', $argv))
                {
                    echo "[".get_class($e)."]";
                    if($e->getMessage()) echo"\r\n\t\t".$e->getMessage();
                    echo "\r\n\r\n\t\t".str_replace("\n", "\n\t\t", $e->getTraceAsString())."\r\n";
                    echo "\033[22;30m";
                    echo "\r\n";
                } else
                {
                    echo "\033[22;31m[FAILED]\033[22;30m";
                    echo "\r\n";
                }
                $exit = 1;
                if (in_array('-b', $argv)) exit($exit);
            }
        }
    }
}
if (in_array('-q', $argv)) ob_clean();
exit($exit);

function __find_tests($directory)
{
    $found = array();
    if (($dir = opendir($directory)) != false)
    {
        while (false !== ($entry = readdir($dir)))
        {
            $full = $directory.DIRECTORY_SEPARATOR.$entry;
            if(is_dir($full))
            {
                if (strpos($entry, '.') === 0) continue;
                $found = array_merge($found, __find_tests($full));
            } elseif ($entry == '_test.php')
            {
                $found[] = $full;
            }
        }
    }
    return $found;
}

function __find_autoload($directory)
{
    $found = false;
    if (($dir = opendir($directory)) != false)
    {
        while (false !== ($entry = readdir($dir)))
        {
            $full = $directory.DIRECTORY_SEPARATOR.$entry;
            if(is_dir($full))
            {
                if (strpos($entry, '.') === 0) continue;
                $found = __find_autoload($full);
            } elseif (strpos(strtolower($entry), 'autoload') !== false)
            {
                $found = $full;
            }
            if ($found != false) return $found;
        }
    }
    return $found;
}

function usage()
{
    echo "\r\n";
    echo "Xendri Framework unit testing Tool\r\n";
    echo "version: 0.1.2\r\n\r\n";
    echo 'usage: unit_test [args] <directory>'."\r\n";
    echo "\r\nArguments: \r\n";
    echo "\t".sprintf('%-20s', "-f")."\tprint full error information\r\n";
    echo "\t".sprintf('%-20s', "-q")."\tverbose output\r\n";
    echo "\t".sprintf('%-20s', "-b")."\tbreak on error\r\n";
    echo "\t".sprintf('%-20s', "-h, -v, --help")."\tprint this screen\r\n";
    die("\r\n");
}

function _ob_handler($data)
{
    return $data."\033[22;30m";
}

function myErrorHandler($errno, $errstr, $errfile, $errline)
{
    echo "\033[22;31mPHP ERROR: $errstr at $errfile:$errline\033[22;30m\r\n";
    return true;
}

?>
